#pragma  once

#include "stdafx.h"


using namespace std;

class QGraphicsSceneMouseEvent;
class SceneView;
class Common;
class ConnectionPoint;
class Connector;
class Title;
class ParametersModel;
class Indicator;
class Sensor;
class Delegate;

class ItemScene : public QGraphicsObject
{
	Q_OBJECT

public:
	static const enum itemType_t {NODE, PIPE, VALVE, PUMP, INNER_NODE};
	ItemScene(QWeakPointer<SceneView> _scene, const itemType_t &_type, const QString &_name, const QPointF &_pos);
	ItemScene(QWeakPointer<SceneView> _scene, const itemType_t &_type);
	~ItemScene();

	QRectF boundingRect() const;
	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
	void addConnectionPoint(QSharedPointer<ItemScene> _source);
	QString getStringType();
	vector<QSharedPointer<ConnectionPoint>> getListOfConnectionPoint(){ return list_of_connection_point; }
	vector<QSharedPointer<ConnectionPoint>> list_of_connection_point;
	bool isAllowedManyConnectors(){ return allowedManyConnectors; }
	QRectF getSize(){ return size; }
	itemType_t getType(){ return type; }
	//QSharedPointer<Indicator> indicator;
	QSharedPointer<Title> title;
	//void setIndicator(QSharedPointer<Indicator> _indicator){ indicator = _indicator; }
	void setTitle(QSharedPointer<Title> _title){ title = _title; init_model();}
	QString getTitleText();
	void setSize(const QRectF &_size){ size = _size; updateConnectionPointPosition(); update(); }
	QSharedPointer<ParametersModel> getModel(){ return model; }
	QSharedPointer<ConnectionPoint> connectionPointAt(int index){ if(index >= 0 && index < list_of_connection_point.size()) return list_of_connection_point[index]; return QSharedPointer<ConnectionPoint>(); }
	bool typeIsNode();
	QVariant getParameter(const QString &name, const QString &script = "COMMON");
	vector<Sensor*> list_of_sensor;
	void addSensor(Sensor* _sensor){ list_of_sensor.push_back(_sensor); }
	void updateAllSensorPosition();
	QVector<double> getCoordinate();
	Sensor* getSensor(){ return sensor; }
	void setSensor(Sensor* _sensor){ sensor = _sensor; }
	void setPosition(const QPointF &_pos);
private:
	QWeakPointer<SceneView> scene;	
	const itemType_t type;
	QSharedPointer<ParametersModel> model;
	QSharedPointer<Delegate> delegate;
	Sensor *sensor;
	QRectF size;
	bool resize;
	bool allowedManyConnectors;
	QVector<QPointF> pipe_profile;
	double pipe_length;
	void setSize();
	void drawNode(QPainter *painter);
	void drawPipe(QPainter *painter);
	void drawValve(QPainter *painter);
	void drawPump(QPainter *painter);
	void drawInnerNode(QPainter *painter);
	void init_model();

	void updateConnectionPointPosition();
	void displayProfileOnPipe(const QVector<QPointF> &_point_array);
protected:
	void mousePressEvent(QGraphicsSceneMouseEvent *event);
	void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
	void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
	void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
	void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
	void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
	QVariant itemChange(GraphicsItemChange change, const QVariant &value);
private slots:
	void getNewParameterValue(const QString &_name, const QVariant &_value);
	void update_parameters();
	void showIndicator();
	void showIndicatorLine();
	void showSensorEditor();
	void removeItem();
	void editSensorList();
	void func(const QString &_parameter_name);
	void removeScriptParameter(const QString &script_name);
	void addScriptParameter(const QString &script_name);
public slots:
	void updateSensorPosition(Sensor *_sensor);
signals:
	void setNewParameterValue(const QString &_name, const QVariant &_value);
};

class ConnectionPoint : public QGraphicsObject
{
	Q_OBJECT

public:
	ConnectionPoint(QWeakPointer<SceneView> _scene, QWeakPointer<ItemScene> _source, const QPointF &_position_relative_source);
	~ConnectionPoint();

	QRectF boundingRect() const;
	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
	void adjust();
	void setAccepted(bool _accepted){ accepted = _accepted; }
	bool isAccepted(){ return accepted; }
	bool isAllowedAddConnector(){ return (!connectors.size() || source.data()->isAllowedManyConnectors()); }
	void addConnector(QWeakPointer<Connector> _connector){ connectors.push_back(_connector); }
	void removeConnector(QWeakPointer<Connector> _connector){ connectors.erase(find(connectors.begin(), connectors.end(), _connector)); }
	QWeakPointer<Connector> getConnector(int index){ if (!connectors.size()) return QWeakPointer<Connector>(); return connectors[index]; }
	void setPositionRelativeSource(QPointF _position_relative_source){ position_relative_source = _position_relative_source; adjust(); }
	QPointF getPositionRelativeSource(){ return position_relative_source; }
	QString getParentName(){ return source.data()->getTitleText(); }
	ItemScene::itemType_t getParentType(){ return source.data()->getType(); }
	int getIndexInParentsList();
    ItemScene* getParent(){ return source.data(); }
	bool isChild(QWeakPointer<Connector> _connector);
	bool parentIsNode(){ return source.data()->typeIsNode(); }
//	QSharedPointer<Vertex> getVertex(){ if (connectors.size()) return connectors[0].data()->vertex; return 	QSharedPointer<Vertex>(); }
private:
	vector<QWeakPointer<Connector>> connectors;
	QWeakPointer<SceneView> scene;
	QWeakPointer<ItemScene> source;
	QPointF position_relative_source;
	bool accepted;
protected:
	void mousePressEvent(QGraphicsSceneMouseEvent *event);
	
};

class Title : public QGraphicsTextItem{
	Q_OBJECT
public:
	Title(QWeakPointer<SceneView> _scene, QWeakPointer<QGraphicsObject> _source, const QPointF &_position_relative_source, const QString &_text = "", const QString &_type = "");
	void adjust(const QPointF &_pos);
	void setText(QString _text){ text = _text; setPlainText(text); }
	QString getText(){ return text; }
	bool isUniqueName(const QString &_name);
protected:
	void mousePressEvent(QGraphicsSceneMouseEvent *event);
	void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
	void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
	void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
private:
	QString text;
	QWeakPointer<SceneView> scene;
	QWeakPointer<QGraphicsObject> source;
	QPointF position_relative_source;
	QString getDefaultName(const QString &_type);
};
